import { _decorator, Component, EventTouch, Node, UITransform, v3, Vec3, Animation, Sprite, Color } from 'cc';
const { ccclass, property } = _decorator;

/**
 * 摇杆脚本
 */
@ccclass('JoystickScript')
export class JoystickScript extends Component {

    @property({
        type: Node,
        tooltip : '摇杆中间的圆圈'
    })
    private centerNode: Node;
  
    @property({
        type: Node,
        tooltip : '摇杆背景'
    })
    private bgNode: Node;

    @property({
        type: Node,
        tooltip : '英雄（角色）节点'
    })
    private heroNode: Node;

    @property({
        type: Animation,
        tooltip : '角色帧动画'
    })
    private animation: Animation | null = null;

    @property({
        type: Sprite,
        tooltip : 'ui节点'
    })
    private uiSprite: Sprite | null = null;
    private uiSpriteDefaultColor = new Color(255, 255, 255, 128);//摇杆默认的颜色：半透明
    private uiSpriteTouchColor = new Color(255, 255, 255, 255);//摇杆触摸的颜色：去掉透明度

    private uiTransfrom: UITransform;

    /**
     * 中间圆圈最大的移动半径
     */
    private maxR: number = 100;

    /**
     * 最小速度
     */
    private speedMin: number = 100;
    /**
     * 最大速度
     */
    private speedMax: number = 300;
    /**
     * 每一帧添加的速度
     */
    private tickAddSpeed: number = 100;
     /**
     * 当前速度
     */
    private curSpeed: number = this.speedMin;

    private isTouchIng: boolean = false;
    private startPos = new Vec3(0, 0, 0);
    private changePos = new Vec3(0, 0, 0);

    /**
     * 角色移动时X轴的最小值
     */
    private heroMinX = -600;
    /**
     * 角色移动时X轴的最大值
     */
    private heroMaxX = 600;
    /**
     * 角色移动时候Y方法最小值（这个值是在界面上踩在碰撞体的位置）
     */
    private heroMinY = -260;

    /**
     * 角色站立和喷跑的状态
     */
    private stopState: string = 'stop';
    private runState: string = 'run';
    private state: string = this.stopState;
    private preState: string = this.state;

    start() {
        this.uiTransfrom = this.node.getComponent(UITransform);
        this.openTouchEvent();
    }

    /**
     * 注册触摸相关事件
     */
    openTouchEvent() {
        this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.node.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);

        this.node.on(Node.EventType.TOUCH_END, this.onTouchEnd, this);
        this.node.on(Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
    }

    onTouchStart(event: EventTouch) {
        console.log('触摸摇杆开始');
        this.isTouchIng = true;
        this.curSpeed = this.speedMin;
        this.uiSprite.color = this.uiSpriteTouchColor;

        //将摇杆的位置为触摸起点的位置(将世界坐标转换为摇杆下的本地坐标)
        const eventUIPos = event.getUILocation();
        const curPos = this.uiTransfrom.convertToNodeSpaceAR(v3(eventUIPos.x, eventUIPos.y, 0));

        console.log(`触摸起点的坐标==>${eventUIPos}, 转为摇杆UI节点下后的坐标为==>${curPos}`)

        this.bgNode.setPosition(curPos.x, curPos.y);
        this.centerNode.setPosition(curPos.x, curPos.y);
        this.bgNode.active = true;
        this.centerNode.active = true;

        //记录摇杆开始的位置
        this.startPos.set(curPos.x, curPos.y);
    }

    onTouchMove(event: EventTouch) {
        console.log('触摸摇杆移动')

        //触摸移动时改变小球的位置
        const eventUIPos = event.getUILocation();
        const curPos = this.uiTransfrom.convertToNodeSpaceAR(v3(eventUIPos.x, eventUIPos.y, 0));
        
        this.changePos.set(curPos.x - this.startPos.x, curPos.y - this.startPos.y);
        const len = this.changePos.length();

        const scalar = len > this.maxR ? this.maxR : len;
        const out = this.changePos.normalize().multiplyScalar(scalar);
        this.centerNode.setPosition(this.startPos.x + out.x, this.startPos.y + out.y);

        this.state = 'run';
    }

    onTouchEnd(event: EventTouch) {
        console.log('触摸摇杆结束')
        this.isTouchIng = false;
        this.curSpeed = this.speedMin;
        this.uiSprite.color = this.uiSpriteDefaultColor;

        //将摇杆的位置恢复为原来的位置
        this.bgNode.setPosition(0, 0);
        this.centerNode.setPosition(0, 0);
        this.changePos.set(0, 0);

        this.state = this.stopState;
    }

    update(deltaTime: number) {
        this.move(deltaTime)
        this.playAnimation()
    }

    private move(deltaTime: number) {
        if (!this.isTouchIng) {
            return;
        }
        const joyDir = this.changePos;
        const dir = joyDir.normalize();
        //console.log(`当前移动方向==>${dir}`)

        const moveDir = this.calculateXMoveDir(dir, 60);
        if (moveDir == 0) {
            return;
        }

        //水平翻转
        const scaleX = Math.abs(this.heroNode.scale.x);
        const scaleY = Math.abs(this.heroNode.scale.y);
        if (moveDir < 0) {
            this.heroNode.scale.set(-scaleX, scaleY, 0);
        } else {
            this.heroNode.scale.set(scaleX, scaleY, 0);
        }

        //更新角色的x坐标
        this.curSpeed += deltaTime * this.tickAddSpeed;
        this.curSpeed = Math.min(this.curSpeed, this.speedMax);
        const heroNodeX = this.heroNode.position.x;
        const heroNodeY = this.heroNode.position.y;
        console.log(`角色当前移动速度==>${this.curSpeed}`)
        //console.log(`角色当前位置==>${this.heroNode.position}`)

        let newheroNodeX = heroNodeX + dir.x * deltaTime * this.curSpeed;
        let newheroNodeY = heroNodeY;//Y抽方向不做移动

        //维护边界，不让角色跑出界面
        newheroNodeY = Math.max(newheroNodeY, this.heroMinY)

        newheroNodeX = Math.max(newheroNodeX, this.heroMinX);
        newheroNodeX = Math.min(newheroNodeX, this.heroMaxX);
        this.heroNode.setPosition(newheroNodeX, newheroNodeY);

        this.state = this.runState;
    }

    /**
     * 计算X轴的移动方向
     * 
     * @param vector  归一化的二维向量
     * @param angle 角度
     * @returns 1向右，-1向左，0不移动
     */
    private calculateXMoveDir(vector: Vec3, angle: number): number {
        if (vector.x == 0) {
            return 0;
        }
        // 将角度转换为弧度
        let radian = angle * (Math.PI / 180);
        // 计算指定角度的余弦值
        let cosAngle = Math.cos(radian);

        // 水平向左(向右)的单位向量
        const x = vector.x < 0 ? -1 : 1;
        let tempVector = v3(x, 0, 0);

        // 计算向量与向左(向右)向量的点积
        let dotProduct = vector.dot(tempVector);

        if (vector.x < 0 && dotProduct > cosAngle) {
            //console.log(`向左移动的夹角小于 ${angle} 度`);
            return -1;
        }
        if (vector.x > 0 && dotProduct > cosAngle) {
            //console.log(`向右移动的夹角小于 ${angle} 度`);
            return 1;
        }
        return 0;
    }

    public playAnimation() {
        if (this.preState == this.state) {
            return;
        }
        if (this.animation) {
            this.animation.play(this.state);
            this.preState = this.state;
        }
    }
}


